import time
import json
import logging
import re
import os
import asyncio
import urllib.parse
from pathlib import Path
from typing import Dict, Any, Optional, List

from app.utils.feishu_bitable_processor import process_feishu_record_cell
from app.models.schemas import ProcessingRequest
from app.utils.text_utils import extract_json_from_text, generate_timing_visualization
from app.clients.volcano_client import VolcanoClient
from app.services.processor_service import create_processor
from app.utils.feishu_spreadsheet import FeishuSpreadsheetUtil
from app.utils.zxy_get import SimpleNotesFetcher
from config.settings import ZXY_API_BASE_URL, ZXY_API_SECRET
import httpx

from prompts import (
    PROMPT_TOPIC_SYSTEM, PROMPT_TOPIC_USER,
    PROMPT_STYLE_JUDGMENT_SEEDING_SYSTEM,
    PROMPT_STYLE_JUDGMENT_SEEDING_USER,
    PROMPT_STYLE_JUDGMENT_EVALUATION_SYSTEM,
    PROMPT_STYLE_JUDGMENT_EVALUATION_USER,
    PROMPT_SEEDING_SINGLE_PRODUCT_SYSTEM, PROMPT_SEEDING_SINGLE_PRODUCT_USER,
    PROMPT_SEEDING_UNBOXING_OUTFIT_SYSTEM, PROMPT_SEEDING_UNBOXING_OUTFIT_USER,
    PROMPT_SEEDING_VLOG_DAILY_SYSTEM, PROMPT_SEEDING_VLOG_DAILY_USER,
    PROMPT_SEEDING_GOODS_COLLECTION_SYSTEM, PROMPT_SEEDING_GOODS_COLLECTION_USER,
    PROMPT_SEEDING_OTHER_SYSTEM, PROMPT_SEEDING_OTHER_USER
)

from app.core.request_context import get_request_id

from app.utils.logger import get_logger

logger = get_logger(__name__)


class ContentService:
    async def generate_content_strategy(self, data):
        # 调试：在服务开始时检查 request_id
        current_request_id = get_request_id()
        print(f"🔍 [服务调试] generate_content_strategy 开始，当前 request_id: {current_request_id}")

        logger.info("【前置准备】zxy_get数据转换完成，caption长度：693，图片数量：5")
        # ... 其他代码

    async def process_topic(self, data):
        # 调试：检查 request_id
        current_request_id = get_request_id()
        print(f"🔍 [服务调试] process_topic 开始，当前 request_id: {current_request_id}")

        logger.info("【话题分析】开始，ProductHighlights长度：862")


def extract_user_uuid_from_url(url: str) -> Optional[str]:
    try:
        parsed_url = urllib.parse.urlparse(url)
        path_segments = [seg for seg in parsed_url.path.split('/') if seg.strip()]
        return path_segments[-1] if path_segments else None
    except Exception as e:
        logger.error(f"拆分URL获取达人ID失败：{str(e)}", exc_info=True)
        return None


async def fetch_user_nickname(user_uuid: str) -> Optional[str]:
    """
    通过用户UUID获取用户昵称
    
    Args:
        user_uuid: 用户UUID
        
    Returns:
        用户昵称，如果获取失败则返回None
    """
    if not user_uuid:
        return None
        
    try:
        api_url = f"https://zongsing.com/prod-api/platform/agent/homepage/getXhsUserBasicData/{user_uuid}"
        async with httpx.AsyncClient() as client:
            response = await client.get(api_url)
            if response.status_code == 200:
                api_result = response.json()
                # 提取data对象中的用户信息
                if "data" in api_result and isinstance(api_result["data"], dict):
                    user_data = api_result["data"]
                    if "nickname" in user_data:
                        return user_data["nickname"]
            else:
                logger.error(f"Failed to fetch user nickname, status code: {response.status_code}")
    except Exception as e:
        logger.error(f"Error fetching nickname from API: {str(e)}")
    
    return None


async def process_topic(ProductHighlights, volcano_client):
    logger.info(f"【话题分析】开始，ProductHighlights长度：{len(ProductHighlights)}")
    user_prompt = PROMPT_TOPIC_USER.format(brief=ProductHighlights)
    result = await volcano_client.call_volcano_api(
        system_prompt=PROMPT_TOPIC_SYSTEM,
        user_prompt=user_prompt
    )
    return extract_json_from_text(result)


async def process_creator_style(caption, image_paths, direction, volcano_client):
    logger.info(f"【达人风格解析】开始，配文长度：{len(caption)}，图片数量：{len(image_paths)}")
    from prompts import PROMPT_CREATOR_STYLE_NEW_SYSTEM, PROMPT_CREATOR_STYLE_NEW_USER
    user_prompt = PROMPT_CREATOR_STYLE_NEW_USER.format(caption=caption)

    raw_response = await volcano_client.call_volcano_api(
        system_prompt=PROMPT_CREATOR_STYLE_NEW_SYSTEM,
        user_prompt=user_prompt,
        image_paths=image_paths
    )
    parsed_result = extract_json_from_text(raw_response)
    logger.info(f"【达人风格解析完整结果】\n{json.dumps(parsed_result, ensure_ascii=False, indent=2)}")
    return parsed_result


async def process_style_judgment(
        product_name: str,
        ProductHighlights: str,
        creator_style_full: Dict[str, Any],
        outline_advice: str,
        direction: str,
        requirements: str,  # 全面替代原request参数
        notice: Optional[str] = None,
        extra_requirements: Optional[str] = None  # 变量名从extra_request改为extra_requirements
) -> str:
    logger.info(f"【风格判断】开始，方向：{direction}，基于完整达人风格解析结果进行判断")
    notice = notice or "无特殊注意事项"
    extra_requirements = extra_requirements or "无额外需求"  # 变量名替换

    creator_style_str = json.dumps(creator_style_full, ensure_ascii=False, indent=2)

    direction_lower = direction.lower()
    if "种草" in direction_lower:
        sys_prompt = PROMPT_STYLE_JUDGMENT_SEEDING_SYSTEM
        logger.info(f"检测到方向包含'种草'，使用种草类系统提示")
    elif "测评" in direction_lower:
        sys_prompt = PROMPT_STYLE_JUDGMENT_EVALUATION_SYSTEM
        logger.info(f"检测到方向包含'测评'，使用测评类系统提示")
    else:
        # 如果都不包含，使用默认提示或报错（根据需求调整）
        logger.warning(f"方向'{direction}'未包含'种草'或'测评'关键词，默认使用种草类")
        sys_prompt = PROMPT_STYLE_JUDGMENT_SEEDING_SYSTEM

    # 替换所有request为requirements
    user_prompt = f"""
    产品名称：{product_name}
    产品亮点：{ProductHighlights}
    达人风格解析全部内容：
    {creator_style_str}
    大纲建议：{outline_advice}
    必要入参：{requirements}
    注意事项：{notice}
    额外需求：{extra_requirements}  # 变量名替换
    """.strip()

    volcano_client = VolcanoClient()
    try:
        api_response = await volcano_client.call_volcano_api(sys_prompt, user_prompt)
        return re.sub(r'[\x00-\x1F\x7F]', '', api_response.strip())
    finally:
        await volcano_client.close()


async def generate_content_strategy(
        request: ProcessingRequest,
        volcano_client
) -> Dict[str, Any]:
    timing_data = {}
    start_time = time.time()

    try:
        # 使用正则表达式匹配关键词
        seeding_pattern = re.compile(r'(种|草|vlog)')
        evaluation_pattern = re.compile(r'(测|评|选购|指南)')
        
        if seeding_pattern.search(request.direction):
            direction_type = "seeding"
        elif evaluation_pattern.search(request.direction):
            direction_type = "evaluation"
        else:
            raise Exception(f"方向'{request.direction}'错误，必须包含'种|草'、'vlog'、'开箱'之一或'测|评'、'选购'、'指南'之一")

        if not request.ProductHighlights:
            raise Exception("请求体缺少必填参数：ProductHighlights（产品亮点）")
        if not request.product_name:
            raise Exception("请求体缺少必填参数：product_name（产品名称）")
        if not request.xhs_link:
            raise Exception("请求体缺少必填参数：xhs_link（达人链接）")
        if not request.requirements:  # 仅校验requirements，不再校验request
            raise Exception("请求体缺少必填参数：requirements（必要入参）")
        if not request.outline_advice:
            raise Exception("请求体缺少必填参数：outline_advice（大纲建议）")
            

        # 2. 达人数据提取（无request相关引用，不变）
        influencer_start = time.time()
        user_uuid = extract_user_uuid_from_url(request.xhs_link)
        if not user_uuid:
            raise Exception(f"从URL提取达人ID失败：{request.xhs_link}")

        zxy_fetcher = SimpleNotesFetcher(ZXY_API_BASE_URL, ZXY_API_SECRET)
        zxy_result = zxy_fetcher.fetch_recent_5_notes(user_uuid, 180)
        if zxy_result["status"] != "success" or not zxy_result["data"]["raw_notes"]:
            raise Exception(f"zxy_get获取达人数据失败：{zxy_result.get('msg', '未知错误')}")

        raw_notes = zxy_result["data"]["raw_notes"]
        document_parts = []
        image_urls = []
        for note in raw_notes:
            note_text = (
                f"笔记标题：{note.get('title', '无标题')}\n"
                f"笔记简介：{note.get('description', '无简介')}\n"
                f"笔记内容：{note.get('content', '无内容')}\n"
                f"发布时间：{note.get('publicTime', '未知时间')}\n"
            )
            document_parts.append(note_text)
            images_str = note.get("imagesList", "")
            if images_str:
                note_images = [img.strip() for img in images_str.split(",") if img.strip()]
                image_urls.extend(note_images)
        image_urls = list(set(image_urls))
        influencer_data = {
            "document": "\n\n".join(document_parts),
            "image_urls": image_urls
        }
        timing_data["influencer_extraction"] = time.time() - influencer_start
        logger.info(
            f"【前置准备】zxy_get数据转换完成，caption长度：{len(influencer_data['document'])}，图片数量：{len(image_urls)}")

        # 3. 前序任务执行（不变）
        parallel_start = time.time()
        topic_result, creator_style_result = await asyncio.gather(
            process_topic(request.ProductHighlights, volcano_client),
            process_creator_style(
                caption=influencer_data["document"],
                image_paths=influencer_data["image_urls"],
                direction=request.direction,
                volcano_client=volcano_client
            )
        )
        timing_data["pre_parallel_processing"] = time.time() - parallel_start

        # 4. 风格判断（全面替换request为requirements）
        style_judge_start = time.time()
        style_judgment_result = await process_style_judgment(
            product_name=request.product_name,
            ProductHighlights=request.ProductHighlights,
            creator_style_full=creator_style_result,
            outline_advice=request.outline_advice,
            direction=request.direction,
            requirements=request.requirements,  # 传入requirements
            notice=request.notice,
            extra_requirements=request.requirements  # 原extra_request替换为requirements（全面替代）
        )
        timing_data["style_judge_processing"] = time.time() - style_judge_start

        # 5. 打印前序结果日志（不变）
        logger.info("\n" + "=" * 60)
        logger.info("【任务1：话题分析输出（JSON解析后）】")
        logger.info(f"类型：{type(topic_result)}")
        logger.info(f"内容：\n{json.dumps(topic_result, ensure_ascii=False, indent=2)}")
        logger.info("-" * 60)
        logger.info("【任务2：达人风格解析输出（完整JSON）】")
        logger.info(f"类型：{type(creator_style_result)}")
        logger.info(f"内容：\n{json.dumps(creator_style_result, ensure_ascii=False, indent=2)}")
        logger.info("-" * 60)
        logger.info("【任务3：风格判断输出（基于完整达人风格）】")
        logger.info(f"类型：{type(style_judgment_result)}")
        logger.info(f"内容：\n{style_judgment_result}")
        logger.info("=" * 60 + "\n")

        # 6. 处理器执行（全面替换request为requirements）
        processor_output = None
        
    
        
        if seeding_pattern.search(request.direction):
            match_start = time.time()
            target_directions = [
                ("单品种草", ["单品", "单品种草", "单个产品"]),
                ("开箱+穿搭", ["开箱", "穿搭", "开箱穿搭"]),
                ("vlog日常植入", ["vlog", "日常植入", "vlog植入"]),
                ("好物合集", ["合集", "好物合集", "多品合集"])
            ]
            matched_direction = "seeding_其他"
            style_judgment_lower = style_judgment_result.lower()
            for dir_name, keywords in target_directions:
                if any(keyword in style_judgment_lower for keyword in keywords):
                    matched_direction = dir_name
                    break
            logger.info(f"【种草二次匹配】风格判断结果：{style_judgment_result} → 匹配方向：{matched_direction}")
            timing_data["direction_matching"] = time.time() - match_start

            # 原request参数替换为requirements
            seeding_inputs = {
                "creator_style": creator_style_result,
                "topic_result": topic_result,
                "product_highlights": request.ProductHighlights,
                "outline_advice": request.outline_advice,
                "notice": request.notice,
                "requirements": request.requirements,  # 全面替换原request字段
                "matched_direction": matched_direction
            }
            if matched_direction == "seeding_其他":
                seeding_inputs["style_judgment_result"] = style_judgment_result

            from processors.seeding import SeedingProcessor
            seeding_processor = SeedingProcessor(
                volcano_client=volcano_client,
                additional_info=request.notice or ""
            )
            processor_output = await seeding_processor.process(seeding_inputs)
            timing_data["seeding_processor"] = time.time() - match_start

        elif evaluation_pattern.search(request.direction):
            match_start = time.time()
            target_directions = [
                ("单品深度测评视频大纲", ["单品深度", "单品测评", "单个产品测评"]),
                ("横向对比测评视频大纲", ["横向对比", "多品对比", "对比测评"]),
                ("榜单推荐视频大纲", ["榜单", "排名推荐", "榜单测评"])
            ]
            matched_direction = "evaluation_其他"
            style_judgment_lower = style_judgment_result.lower()
            for dir_name, keywords in target_directions:
                if any(keyword.lower() in style_judgment_lower for keyword in keywords):
                    matched_direction = dir_name
                    break
            logger.info(f"【测评二次匹配】风格判断结果：{style_judgment_result} → 匹配方向：{matched_direction}")
            timing_data["evaluation_direction_matching"] = time.time() - match_start

            # 原request参数替换为requirements
            evaluation_inputs = {
                "topic_result": topic_result,
                "creator_style": creator_style_result,
                "product_highlights": request.ProductHighlights,
                "outline_advice": request.outline_advice,
                "notice": request.notice,
                "requirements": request.requirements,  # 全面替换原request字段
                "product_name": request.product_name,
                "matched_direction": matched_direction
            }
            if matched_direction == "evaluation_其他":
                evaluation_inputs["style_judgment_result"] = style_judgment_result

            from processors.evaluation import EvaluationProcessor
            evaluation_processor = EvaluationProcessor(
                volcano_client=volcano_client,
                additional_info=request.notice or ""
            )
            processor_output = await evaluation_processor.process(evaluation_inputs)
            timing_data["evaluation_processor"] = time.time() - match_start

        # 7. 提取处理器的result字段（不变）
        strategy_result = ""
        if isinstance(processor_output, dict):
            strategy_result = processor_output.get("result", "")
            strategy_result = re.sub(r'[\x00-\x1F\x7F]', '', strategy_result)  # 清理特殊字符
            logger.info(f"【提取处理器结果】长度：{len(strategy_result)}，前200字符：{strategy_result[:200]}...")
        else:
            logger.warning(f"处理器输出格式异常（非dict），无法提取result：{type(processor_output)}")

        # 8. 飞书表格操作（不变）
        sheet_start = time.time()
        try:
            # 从blogger_link中提取userUuid并获取昵称作为表格标题
            xhs_link = getattr(request, "xhs_link", "")
            # 从链接中提取userUuid（最后一部分）
            user_uuid = xhs_link.rstrip('/').split('/')[-1] if xhs_link else "默认主题"
            
            # 如果有user_uuid，则通过API获取用户昵称
            sheet_title = "默认主题"
            if user_uuid != "默认主题":
                nickname = await fetch_user_nickname(user_uuid)
                if nickname:
                    sheet_title = nickname
                else:
                    # 如果无法获取昵称，回退到使用原始达人名称
                    sheet_title = request.name
            else:
                # 如果没有user_uuid，使用原始达人名称
                sheet_title = request.name
                
            sheet_title = re.sub(r'[\\/*?:"<>|]', '-', sheet_title)
            sheet_title = sheet_title+"-视频大纲" # 限制标题长度为100个字符
            if not sheet_title.strip():
                sheet_title = "未命名达人"
            logger.info(f"【飞书表格】准备创建表格，标题（纯达人名称）：{sheet_title}")

            spreadsheet_util = FeishuSpreadsheetUtil(
                folder_token=request.folder_token or "AjubfiJyJlFMFEd3HhdcTI0kngd"
            )

            sheet_result = await spreadsheet_util.full_flow(
                sheet_title=sheet_title,
                video_script="",
                strategy_result=strategy_result,
                shot_list=[]
            )
            timing_data["feishu_processing"] = time.time() - sheet_start

            if sheet_result.get("status") != "success":
                raise Exception(f"飞书表格操作失败：{sheet_result.get('message', '未知错误')}")
            logger.info(f"【飞书表格】创建成功！标题：{sheet_title}，链接：{sheet_result.get('spreadsheet_url')}")

        except Exception as e:
            logger.error(f"【飞书表格】操作异常：{str(e)}", exc_info=True)
            raise Exception(f"飞书表格处理失败：{str(e)}")

        # 9. 返回最终结果（不变）
        total_time = time.time() - start_time
        response = {
            "status": "success",
            "message": f"内容策略生成完成，飞书表格标题：{sheet_title}",
            "pre_task_outputs": {
                "topic_analysis": topic_result,
                "creator_style_analysis": creator_style_result,
                "style_judgment": style_judgment_result
            },
            "processor_output": processor_output,
            "feishu_info": {
                "spreadsheet_url": sheet_result.get("spreadsheet_url"),
                "spreadsheet_token": sheet_result.get("spreadsheet_token"),
                "sheet_title": sheet_title
            },
            "timing": {
                "total_seconds": round(total_time, 2),
                "breakdown": timing_data
            }
        }

        record_link = request.record_link if request else None
        if record_link:
            try:

                await process_feishu_record_cell(record_link, "视频大纲创作结果", sheet_result.get("spreadsheet_token"))
                logger.info(f"Successfully updated Feishu bitable record with error for record_link: {record_link}")
            except Exception as e:
                logger.error(f"Failed to update Feishu bitable record with error for record_link {record_link}: {str(e)}")
    
        return response

    except Exception as e:
        logger.error(f"【主流程】处理出错: {str(e)}", exc_info=True)
        response = {
            "status": "error",
            "message": f"处理出错: {str(e)}",
            "timing": timing_data
        }

        record_link = request.record_link if request else None
        if record_link:
            try:
                await process_feishu_record_cell(record_link, "视频大纲创作结果", response)
                logger.info(f"Successfully updated Feishu bitable record with error for record_link: {record_link}")
            except Exception as e:
                logger.error(f"Failed to update Feishu bitable record with error for record_link {record_link}: {str(e)}")

        return response
